﻿using System.Collections.ObjectModel;
using System.Linq;
using Microsoft.TeamFoundation.WorkItemTracking.Client;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using TypeMock.ArrangeActAssert;
using WorkItemAnalyser.Core.Assertions;

namespace WorkItemAnalyser.Test.AssertionTests
{
    [TestClass]
    public class FieldAssertionTests
    {
        [Isolated]
        [TestMethod]
        public void FieldAssertion_OnAssertNullTitle_ShouldReturnNotValid()
        {
            //Arrange
            var workItem = Isolate.Fake.Instance<WorkItem>(Members.ReturnRecursiveFakes, ConstructorWillBe.Ignored);
            Isolate.WhenCalled(() => workItem.Fields["Title"].Value).WillReturn(null);

            var workItems = new Collection<WorkItem>();
            workItems.Add(workItem);

            var assertion = new FieldAssertion("Title", "test");

            //Act
            var results = assertion.Execute(workItems);

            //Assert
            Assert.IsTrue(results.Count() == 1);
            Assert.IsFalse(results.ElementAt(0).IsValid);
        }

        [Isolated]
        [TestMethod]
        public void FieldAssertion_OnAssertNonNullTitle_ShouldReturnValid()
        {
            //Arrange
            var workItem = Isolate.Fake.Instance<WorkItem>(Members.ReturnRecursiveFakes, ConstructorWillBe.Ignored);
            Isolate.WhenCalled(() => workItem.Fields["Title"].Value).WillReturn("test");

            var workItems = new Collection<WorkItem> {workItem};
            var assertion = new FieldAssertion("Title", "test");

            //Act
            var results = assertion.Execute(workItems);

            //Assert
            Assert.IsTrue(results.Count() == 1);
            Assert.IsTrue(results.ElementAt(0).IsValid);
        }

        [Isolated]
        [TestMethod]
        public void FieldAssertion_OnAssertValuesOfEquatableButDifferentTypes_ShouldReturnValid()
        {
            //Arrange
            var workItem = Isolate.Fake.Instance<WorkItem>(Members.ReturnRecursiveFakes, ConstructorWillBe.Ignored);
            Isolate.WhenCalled(() => workItem.Fields["Title"].Value).WillReturn(1);

            var workItems = new Collection<WorkItem> {workItem};
            var assertion = new FieldAssertion("Title", "1");

            //Act
            var results = assertion.Execute(workItems);

            //Assert
            Assert.IsTrue(results.Count() == 1);
            Assert.IsTrue(results.ElementAt(0).IsValid);
        }

        [Isolated]
        [TestMethod]
        public void FieldAssertion_OnAssertValuesOfNonEquatableDifferentType_ShouldReturnNotValid()
        {
            //Arrange
            var workItem = Isolate.Fake.Instance<WorkItem>(Members.ReturnRecursiveFakes, ConstructorWillBe.Ignored);
            Isolate.WhenCalled(() => workItem.Fields["Title"].Value).WillReturn(new FieldAssertion("", ""));

            var workItems = new Collection<WorkItem> {workItem};
            var assertion = new FieldAssertion("Title", "1");

            //Act
            var results = assertion.Execute(workItems);

            //Assert
            Assert.IsTrue(results.Count() == 1);
            Assert.IsFalse(results.ElementAt(0).IsValid);
        }

        [Isolated]
        [TestMethod]
        public void FieldAssertion_OnAssertValuesOfSameComplexTypeandValue_ShouldReturnValid()
        {
            var dummyObject = new FieldAssertion("", "");
            var workItem = Isolate.Fake.Instance<WorkItem>(Members.ReturnRecursiveFakes, ConstructorWillBe.Ignored);
            Isolate.WhenCalled(() => workItem.Fields["Title"].Value).WillReturn(dummyObject);

            var workItems = new Collection<WorkItem> {workItem};
            var assertion = new FieldAssertion("Title", dummyObject);

            //Act
            var results = assertion.Execute(workItems);

            //Assert
            Assert.IsTrue(results.Count() == 1);
            Assert.IsTrue(results.ElementAt(0).IsValid);
        }

        [Isolated]
        [TestMethod]
        public void FieldAssertion_OnAssertValuesOfSameComplexTypeButDifferentValue_ShouldReturnInvalid()
        {
            //Arrange
            var dummyObject = new FieldAssertion("", "");
            var workItem = Isolate.Fake.Instance<WorkItem>(Members.ReturnRecursiveFakes, ConstructorWillBe.Ignored);
            Isolate.WhenCalled(() => workItem.Fields["Title"].Value).WillReturn(dummyObject);

            var workItems = new Collection<WorkItem> {workItem};
            var assertion = new FieldAssertion("Title", new FieldAssertion("", ""));

            //Act
            var results = assertion.Execute(workItems);

            //Assert
            Assert.IsTrue(results.Count() == 1);
            Assert.IsFalse(results.ElementAt(0).IsValid);
        }

        [Isolated]
        [TestMethod]
        public void FieldAssertion_OnAssertValueTypeOfDifferentValueType_ShouldReturnInvalid()
        {
            //Arrange
            var integer = 1;
            var workItem = Isolate.Fake.Instance<WorkItem>(Members.ReturnRecursiveFakes, ConstructorWillBe.Ignored);
            Isolate.WhenCalled(() => workItem.Fields["Title"].Value).WillReturn(integer);

            var workItems = new Collection<WorkItem> {workItem};
            var assertion = new FieldAssertion("Title", new FieldAssertion("Title", byte.Parse("00000100")));

            //Act
            var results = assertion.Execute(workItems);

            //Assert
            Assert.IsTrue(results.Count() == 1);
            Assert.IsFalse(results.ElementAt(0).IsValid);
        }

        [Isolated]
        [TestMethod]
        public void FieldAssertion_OnAssertManyWorkItems_ResultCountShouldMatchWorkItemCount()
        {
            //Arrange
            var max = 10;
            var workItems = new Collection<WorkItem>();
            var fakeWorkItem = Isolate.Fake.Instance<WorkItem>();
            Isolate.WhenCalled(() => fakeWorkItem.Fields["Title"].Value).WillReturn("test");

            for (int i = 0; i < max; i++)
            {
                workItems.Add(fakeWorkItem);
            }

            var assertion = new FieldAssertion("Title", "test");

            //Act
            var results = assertion.Execute(workItems);

            //Assert
            Assert.IsTrue(results.Count() == max);
        }
    }
}